from rest_framework import serializers
from .models import Enrollment
from apps.courses.models import Course
from apps.users.models import User


class EnrollmentSerializer(serializers.ModelSerializer):
    """选课序列化器"""

    class Meta:
        model = Enrollment
        fields = [
            'id', 'student', 'course', 'enrollment_date', 'status',
            'attendance_score', 'homework_score', 'midterm_score',
            'final_score', 'total_score', 'grade', 'remarks'
        ]


class EnrollmentListSerializer(serializers.ModelSerializer):
    """学生选课列表序列化器"""
    course_id = serializers.IntegerField(source='course.id', read_only=True)
    course_code = serializers.CharField(source='course.course_code', read_only=True)
    course_name = serializers.CharField(source='course.course_name', read_only=True)
    teacher_name = serializers.CharField(source='course.teacher.real_name', read_only=True)
    credit_hours = serializers.IntegerField(source='course.credit_hours', read_only=True)
    semester = serializers.CharField(source='course.semester', read_only=True)
    classroom = serializers.CharField(source='course.classroom', read_only=True)
    schedule = serializers.CharField(source='course.schedule', read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    class Meta:
        model = Enrollment
        fields = [
            'id', 'course_id', 'course_code', 'course_name', 'teacher_name', 'credit_hours',
            'semester', 'classroom', 'schedule', 'enrollment_date', 'status',
            'status_display', 'attendance_score', 'homework_score',
            'midterm_score', 'final_score', 'total_score', 'grade', 'remarks'
        ]


class TeacherEnrollmentListSerializer(serializers.ModelSerializer):
    """教师查看选课学生列表序列化器"""
    course_id = serializers.IntegerField(source='course.id', read_only=True)
    course_code = serializers.CharField(source='course.course_code', read_only=True)
    course_name = serializers.CharField(source='course.course_name', read_only=True)
    credit_hours = serializers.IntegerField(source='course.credit_hours', read_only=True)
    semester = serializers.CharField(source='course.semester', read_only=True)
    classroom = serializers.CharField(source='course.classroom', read_only=True)
    schedule = serializers.CharField(source='course.schedule', read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    # 学生信息
    student_id = serializers.CharField(source='student.student_id', read_only=True)
    student_name = serializers.CharField(source='student.real_name', read_only=True)
    student_email = serializers.CharField(source='student.email', read_only=True)
    student_department = serializers.CharField(source='student.department', read_only=True)

    class Meta:
        model = Enrollment
        fields = [
            'id', 'course_id', 'course_code', 'course_name', 'credit_hours',
            'semester', 'classroom', 'schedule', 'enrollment_date', 'status',
            'status_display', 'student_id', 'student_name', 'student_email',
            'student_department', 'attendance_score', 'homework_score',
            'midterm_score', 'final_score', 'total_score', 'grade', 'remarks'
        ]


class AdminEnrollmentListSerializer(serializers.ModelSerializer):
    """管理员查看所有选课记录序列化器"""
    course_id = serializers.IntegerField(source='course.id', read_only=True)
    course_code = serializers.CharField(source='course.course_code', read_only=True)
    course_name = serializers.CharField(source='course.course_name', read_only=True)
    teacher_name = serializers.CharField(source='course.teacher.real_name', read_only=True)
    teacher_id = serializers.CharField(source='course.teacher.teacher_id', read_only=True)
    credit_hours = serializers.IntegerField(source='course.credit_hours', read_only=True)
    semester = serializers.CharField(source='course.semester', read_only=True)
    classroom = serializers.CharField(source='course.classroom', read_only=True)
    schedule = serializers.CharField(source='course.schedule', read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    # 学生信息
    student_id = serializers.CharField(source='student.student_id', read_only=True)
    student_name = serializers.CharField(source='student.real_name', read_only=True)
    student_email = serializers.CharField(source='student.email', read_only=True)
    student_department = serializers.CharField(source='student.department', read_only=True)

    class Meta:
        model = Enrollment
        fields = [
            'id', 'course_id', 'course_code', 'course_name', 'teacher_name',
            'teacher_id', 'credit_hours', 'semester', 'classroom', 'schedule',
            'enrollment_date', 'status', 'status_display', 'student_id',
            'student_name', 'student_email', 'student_department',
            'attendance_score', 'homework_score', 'midterm_score',
            'final_score', 'total_score', 'grade', 'remarks'
        ]


class EnrollmentDetailSerializer(serializers.ModelSerializer):
    """选课详情序列化器"""
    course_id = serializers.IntegerField(source='course.id', read_only=True)
    course_code = serializers.CharField(source='course.course_code', read_only=True)
    course_name = serializers.CharField(source='course.course_name', read_only=True)
    course_description = serializers.CharField(source='course.description', read_only=True)
    teacher_name = serializers.CharField(source='course.teacher.real_name', read_only=True)
    teacher_id = serializers.CharField(source='course.teacher.teacher_id', read_only=True)
    teacher_email = serializers.CharField(source='course.teacher.email', read_only=True)
    credit_hours = serializers.IntegerField(source='course.credit_hours', read_only=True)
    class_hours = serializers.IntegerField(source='course.class_hours', read_only=True)
    semester = serializers.CharField(source='course.semester', read_only=True)
    classroom = serializers.CharField(source='course.classroom', read_only=True)
    schedule = serializers.CharField(source='course.schedule', read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)

    # 学生信息（管理员和教师可见）
    student_id = serializers.CharField(source='student.student_id', read_only=True)
    student_name = serializers.CharField(source='student.real_name', read_only=True)
    student_email = serializers.CharField(source='student.email', read_only=True)
    student_department = serializers.CharField(source='student.department', read_only=True)
    student_class = serializers.CharField(source='student.class_name', read_only=True)

    # 成绩录入相关
    grade_entered_by_name = serializers.CharField(source='grade_entered_by.real_name', read_only=True)

    class Meta:
        model = Enrollment
        fields = [
            'id', 'course_id', 'course_code', 'course_name', 'course_description',
            'teacher_name', 'teacher_id', 'teacher_email', 'credit_hours',
            'class_hours', 'semester', 'classroom', 'schedule', 'enrollment_date',
            'status', 'status_display', 'student_id', 'student_name',
            'student_email', 'student_department', 'student_class',
            'attendance_score', 'homework_score', 'midterm_score',
            'final_score', 'total_score', 'grade', 'grade_entered_by_name',
            'grade_entered_at', 'remarks', 'created_at', 'updated_at'
        ]


class EnrollmentGradeSerializer(serializers.ModelSerializer):
    """成绩录入序列化器"""

    class Meta:
        model = Enrollment
        fields = [
            'attendance_score', 'homework_score', 'midterm_score',
            'final_score', 'total_score', 'grade', 'remarks'
        ]

    def validate_attendance_score(self, value):
        """验证考勤成绩"""
        if value is not None and (value < 0 or value > 100):
            raise serializers.ValidationError("考勤成绩必须在0-100之间")
        return value

    def validate_homework_score(self, value):
        """验证作业成绩"""
        if value is not None and (value < 0 or value > 100):
            raise serializers.ValidationError("作业成绩必须在0-100之间")
        return value

    def validate_midterm_score(self, value):
        """验证期中成绩"""
        if value is not None and (value < 0 or value > 100):
            raise serializers.ValidationError("期中成绩必须在0-100之间")
        return value

    def validate_final_score(self, value):
        """验证期末成绩"""
        if value is not None and (value < 0 or value > 100):
            raise serializers.ValidationError("期末成绩必须在0-100之间")
        return value

    def validate_total_score(self, value):
        """验证总成绩"""
        if value is not None and (value < 0 or value > 100):
            raise serializers.ValidationError("总成绩必须在0-100之间")
        return value

    def validate_grade(self, value):
        """验证等级成绩"""
        if value and value not in ['A', 'B', 'C', 'D', 'F']:
            raise serializers.ValidationError("等级成绩必须是A、B、C、D、F中的一个")
        return value

    def validate(self, data):
        """交叉验证"""
        total_score = data.get('total_score')
        grade = data.get('grade')

        # 如果填写了总成绩，必须填写等级成绩
        if total_score is not None and not grade:
            raise serializers.ValidationError("填写总成绩时必须选择等级成绩")

        # 如果填写了等级成绩，必须填写总成绩
        if grade and total_score is None:
            raise serializers.ValidationError("选择等级成绩时必须填写总成绩")

        # 验证等级成绩与总成绩的匹配性
        if total_score is not None and grade:
            if grade == 'A' and total_score < 90:
                raise serializers.ValidationError("A级成绩要求总分不低于90分")
            elif grade == 'B' and (total_score < 80 or total_score >= 90):
                raise serializers.ValidationError("B级成绩要求总分在80-89分之间")
            elif grade == 'C' and (total_score < 70 or total_score >= 80):
                raise serializers.ValidationError("C级成绩要求总分在70-79分之间")
            elif grade == 'D' and (total_score < 60 or total_score >= 70):
                raise serializers.ValidationError("D级成绩要求总分在60-69分之间")
            elif grade == 'F' and total_score >= 60:
                raise serializers.ValidationError("F级成绩要求总分低于60分")

        return data


class CourseWithEnrollmentSerializer(serializers.ModelSerializer):
    """带选课状态的课程序列化器"""
    teacher_name = serializers.CharField(source='teacher.real_name', read_only=True)
    status_display = serializers.CharField(source='get_status_display', read_only=True)
    enrollment_rate = serializers.SerializerMethodField()
    available_slots = serializers.SerializerMethodField()

    # 学生选课状态相关字段
    enrollment_status = serializers.SerializerMethodField()
    can_enroll = serializers.SerializerMethodField()
    can_drop = serializers.SerializerMethodField()
    enrollment_message = serializers.SerializerMethodField()
    enrollment_date = serializers.SerializerMethodField()

    class Meta:
        model = Course
        fields = [
            'id', 'course_code', 'course_name', 'teacher_name', 'credit_hours',
            'class_hours', 'capacity', 'enrolled_count', 'semester', 'status',
            'status_display', 'enrollment_rate', 'available_slots', 'start_date',
            'end_date', 'classroom', 'schedule', 'description',
            'enrollment_status', 'can_enroll', 'can_drop', 'enrollment_message',
            'enrollment_date', 'created_at', 'updated_at'
        ]

    def get_enrollment_rate(self, obj):
        """计算选课率"""
        if obj.capacity > 0:
            return round((obj.enrolled_count / obj.capacity) * 100, 2)
        return 0

    def get_available_slots(self, obj):
        """计算剩余名额"""
        return max(0, obj.capacity - obj.enrolled_count)

    def get_enrollment_status(self, obj):
        """获取选课状态"""
        request = self.context.get('request')
        if not request:
            return 'unknown'

        user_id = request.META.get('HTTP_USER_ID')
        user_role = request.META.get('HTTP_USER_ROLE')

        if user_role != 'student' or not user_id:
            return 'not_student'

        enrollment = Enrollment.objects.filter(
            student_id=user_id,
            course=obj
        ).first()

        if not enrollment:
            return 'not_enrolled'

        return enrollment.status

    def get_can_enroll(self, obj):
        """是否可以选课"""
        request = self.context.get('request')
        if not request:
            return False

        user_id = request.META.get('HTTP_USER_ID')
        user_role = request.META.get('HTTP_USER_ROLE')

        if user_role != 'student' or not user_id:
            return False

        enrollment = Enrollment.objects.filter(
            student_id=user_id,
            course=obj
        ).first()

        # 未选课或已退选，且课程开放且有容量
        if (not enrollment or enrollment.status == 'dropped') and \
                obj.status == 'active' and \
                obj.enrolled_count < obj.capacity:
            return True

        return False

    def get_can_drop(self, obj):
        """是否可以退课"""
        request = self.context.get('request')
        if not request:
            return False

        user_id = request.META.get('HTTP_USER_ID')
        user_role = request.META.get('HTTP_USER_ROLE')

        if user_role != 'student' or not user_id:
            return False

        enrollment = Enrollment.objects.filter(
            student_id=user_id,
            course=obj,
            status='enrolled'
        ).first()

        # 已选课且没有成绩
        if enrollment and enrollment.total_score is None:
            return True

        return False

    def get_enrollment_message(self, obj):
        """获取选课状态信息"""
        request = self.context.get('request')
        if not request:
            return ''

        user_id = request.META.get('HTTP_USER_ID')
        user_role = request.META.get('HTTP_USER_ROLE')

        if user_role != 'student' or not user_id:
            return '非学生用户'

        enrollment = Enrollment.objects.filter(
            student_id=user_id,
            course=obj
        ).first()

        if not enrollment or enrollment.status == 'dropped':
            if obj.status != 'active':
                return '课程未开放选课'
            elif obj.enrolled_count >= obj.capacity:
                return '课程已满员'
            else:
                return '可以选课'
        elif enrollment.status == 'enrolled':
            if enrollment.total_score is not None:
                return '已有成绩，不能退选'
            else:
                return '已选课，可以退选'
        elif enrollment.status == 'completed':
            return '课程已完成'

        return ''

    def get_enrollment_date(self, obj):
        """获取选课时间"""
        request = self.context.get('request')
        if not request:
            return None

        user_id = request.META.get('HTTP_USER_ID')
        user_role = request.META.get('HTTP_USER_ROLE')

        if user_role != 'student' or not user_id:
            return None

        enrollment = Enrollment.objects.filter(
            student_id=user_id,
            course=obj,
            status__in=['enrolled', 'completed']
        ).first()

        if enrollment:
            return enrollment.enrollment_date.strftime('%Y-%m-%d %H:%M:%S')

        return None


class StudentEnrollmentStatsSerializer(serializers.Serializer):
    """学生选课统计序列化器"""
    total_enrolled = serializers.IntegerField()
    total_completed = serializers.IntegerField()
    total_dropped = serializers.IntegerField()
    total_credits = serializers.IntegerField()
    gpa = serializers.FloatField()
    pass_rate = serializers.FloatField()


class EnrollmentStatisticsSerializer(serializers.Serializer):
    """选课统计数据序列化器"""
    total_enrollments = serializers.IntegerField()
    active_enrollments = serializers.IntegerField()
    completed_enrollments = serializers.IntegerField()
    dropped_enrollments = serializers.IntegerField()
    grade_distribution = serializers.DictField()
    semester_stats = serializers.ListField()
    course_stats = serializers.ListField()


class BatchOperationSerializer(serializers.Serializer):
    """批量操作序列化器"""
    enrollment_ids = serializers.ListField(
        child=serializers.IntegerField(),
        min_length=1,
        error_messages={'min_length': '至少选择一条记录'}
    )


class BatchGradeEntrySerializer(serializers.Serializer):
    """批量成绩录入序列化器"""
    enrollment_ids = serializers.ListField(
        child=serializers.IntegerField(),
        min_length=1,
        error_messages={'min_length': '至少选择一条记录'}
    )
    grade_data = EnrollmentGradeSerializer()

    def validate_enrollment_ids(self, value):
        """验证选课记录ID"""
        if len(value) > 100:
            raise serializers.ValidationError("一次最多只能批量处理100条记录")
        return value